<?php exit();
/*
krutaya doka: http://arduino.esp8266.com/versions/1.6.5-1160-gef26c5f/doc/reference.html
curl -F "file=@css/dropdown.css;filename=/css/dropdown.css" 192.168.4.1/update
server upload: https://github.com/jpswensen/ESP8266_WebGen/blob/master/AdvancedWebServerHuzzah_SPIFFS/AdvancedWebServerHuzzah_SPIFFS.ino
// Функция ESP.deepSleep(microseconds, mode) // Прежим глубокого сна. Для аргумента mode WAKE_RF_DEFAULT, WAKE_RFCAL, WAKE_NO_RFCAL и WAKE_RF_DISABLED.
// Контакт GPIO16 должен быть привязан к RST – чтобы вывести чип из режима глубокого сна.
// Функция ESP.restart() Перезапускает процессор.
// ADC_MODE(ADC_VCC); в самом начале
* UPGRADE: https://github.com/julienrat/esp8266_update_from_spiffs/blob/master/update_from_spiffs.ino
*
* UPDATE: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WebServer/examples/WebUpdate/WebUpdate.ino
*
* if (!f) {
Serial.println("file open failed");
} Serial.println("====== Reading from SPIFFS file =======");
// write 10 strings to file
for (int i=1; i<=10; i++){
String s=f.readStringUntil('\n');
Serial.print(i);
Serial.print(":");
Serial.println(s);
}
stream.findUntil(char target, terminal)
HTTP.on("/list",HTTP_GET, printDirectory);
HTTP.on("/edit",HTTP_DELETE, handleDelete);
HTTP.on("/edit",HTTP_PUT, handleCreate);
HTTP.on("/edit",HTTP_POST, [](){ returnOK(); }, handleFileUpload);
HTTP.onNotFound(handleNotFound);
*/
#include "FS.h"
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <Servo.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
#include <Ticker.h> //Ticker Library
const String DefaultConfig="\n"
"soft=default\n"
"autoupdate=yes\n"
"server_update=http://lleo.me/ESP8266/index.php?ip={ip}&chip={chip}&CHIP={CHIP}&soft={soft}\n"
"server_ping=http://home.lleo.me/ESP8266/index.php?ip={ip}&chip={chip}&CHIP={CHIP}&soft={soft}\n"
"AP_name=ESP8266-{chip}\n"
"AP_password=";
const String DefaultINDEX="<html><body><h1>Connect your WiFi for first time SPIFFS install</h1><p><form method='GET' action='/FM'>"
"<input type='hidden' name='a' value='WIFIconn1'>"
"<br>Login: <input type='text' name='net'>"
"<br>Password: <input type='text' name='pass'>"
"<br><input type='submit' value='Go'></form></body></html>";
#define DEFAULTPORT 80
String WIFICONNECT="";
String LOADED_CONFIG="NO";
String LOOPFILE="";
int8_t servopins[]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
Servo servo1,servo2,servo3,servo4,servo5,servo6,servo7,servo8,servo9,servo10,servo11;
Ticker tim;
unsigned int tim_count=0;
unsigned int tim_motor_detach=0;
unsigned int tim_LoopDelay=0;
// unsigned int tim_PingCounter=0;
void tim_engine() {
tim_count++;
if(tim_LoopDelay) tim_LoopDelay--;
// if(tim_PingCounter) tim_PingCounter--;
if(tim_motor_detach) {
if(! --tim_motor_detach) {
// Serial.println("\n --- detach all servo ---");
for(uint8_t i=0;i<11;i++) { if(servopins[i]!=-1) ServoDetach(String(i)); }
}
}
}
// ADC_MODE(ADC_VCC);
ESP8266WiFiMulti wifiMulti;
DNSServer DNS;
ESP8266WebServer WEB( DEFAULTPORT ); // CF0("WEB_PORT",DEFAULTPORT);
/*
void WiFiEvent(WiFiEvent_t event) {
Serial.printf("\n\t\t[WiFi-event: %d", event);
switch(event) {
case WIFI_EVENT_STAMODE_GOT_IP: Serial.println(" Connected IP: "+ WiFi.localIP().toString()+ " ]"); break;
case WIFI_EVENT_STAMODE_DISCONNECTED: Serial.println(" Lost connection ]"); break;
default: Serial.println(" ]"); break;
}
}
*/
void setup() {
Serial.begin(115200);
Serial.println("\n############### Restart #############");
SPIFFS.begin();
tim.attach(1,tim_engine); // 1 sec
Serial.println(FullInfo());
// WiFi.onEvent(WiFiEvent);
WIFIinit();
// init.txt start
String start=CF("start"); if(start!="") { MOTO(start); } else { start=CF("startfile"); if(start!="") { MOTO(getfile(start)); } }
// Serial.println("FILE `wifi_last.txt`:"+getfile("wifi_last.txt"));
// Serial.println("MD5 `wifi_last.txt`:"+MD5file("wifi_last.txt"));
load_loop("loop.txt");
// ================================================== попытка файла ==================================================
if(WIFICONNECT!="") {
String s=CF("server_ping"); if(s!="") { String otv=file_get_contents(REPER(s)); Serial.println(" ["+otv+"]"); }
if(CF0("autoupdate")) UpgradeALL();
}
// ================================================== попытка файла ==================================================
WEB.on("/favicon.ico",HTTP_GET,WEBNAH);
WEB.on("/generate_204",HTTP_GET,WEBNAH);
WEB.on("/fwlink",HTTP_GET,WEBNAH);
WEB.on("/v1/public/yql",HTTP_GET,WEBNAH);
WEB.on("/gslb/",HTTP_GET,WEBNAH);
WEB.on("/chat",HTTP_POST,WEBNAH);
WEB.on("/time",HTTP_GET,[](){ idip("Time: "+String(tim_count)); });
WEB.on("/reset",HTTP_GET,[](){ ESP.reset(); });
WEB.on("/restart",HTTP_GET,[](){ ESP.restart(); });
WEB.on("/format",HTTP_GET,[](){ SPIFFS.format(); });
WEB.on("/PIN",HTTP_GET,[](){ String a=RE("a"); // Serial.print("\nPIN a="+a);
if(a=="servo") {
String n=RE("n");
String mode=RE("mode");
String s=a+n+" "+mode;
if(mode=="attach") {
String d=RE("d");
if(ServoAttached(n)) { ServoDetach(n); s+=" [detach] "; }
s+" #"+d;
if(ServoAttach(n,d.toInt())) return idip(s+" OK");
return idip(s+"ERROR");
}
if(mode=="detach") {
if( ! ServoAttached(n) ) return idip(s+=" [not attached]");
ServoDetach(n);
if( ServoAttached(n) ) return idip(s+" OK");
return idip(s+" ERROR");
}
if(mode=="go") {
String x=RE("x");
ServoWrite(n,x.toInt());
return idip(s+" TO: "+x);
}
return idip("Error mode");
}
if(a=="pinmode") {
String d=RE("d");
byte dd=(d=="A0" ? A0 : d.toInt() );
String mode=RE("mode");
String s=a+" #"+d+" ["+String(dd)+"] "+mode;
if(mode=="OUTPUT") pinMode(dd,OUTPUT);
else if(mode=="INPUT") pinMode(dd,INPUT);
else if(mode=="INPUT_PULLUP") pinMode(dd,INPUT_PULLUP);
else return idip(s+" ERROR: unknown mode");
return idip(s+" OK");
}
if(a=="pin") {
String d=RE("d");
String mode=RE("mode");
String s=a+" #"+d+" "+mode;
digitalWrite(d.toInt(),mode.toInt());
return idip(s+" OK");
}
return idie("PIN error");
});
// File Manager System
WEB.on("/FM",HTTP_POST,[]() { String a=RE("a");
if(a=="editsave") {
String file=RE("file"); file.replace("..","");
String s=RE("plain");
if(s=="") return idie("Error length 0");
savefile(file,s);
return otprav("clean('editor');salert('saved',300);");
}
/*
Serial.println("\nFM POST a="+a);
HTTPUpload& upload = WEB.upload();
if(!WEB.args()) Serial.println("NO ARGS");
else {
for(uint8_t i=0;i<WEB.args();i++) Serial.println("------> ["+WEB.argName(i)+"]=("+WEB.arg(i)+")");
}
return idie("UPLOAD_FILE_END");
Serial.println("Upload status: "+String(upload.status));
if (upload.status == UPLOAD_FILE_START) { Serial.println("2");
String filename = upload.filename;
Serial.printf("UPLOAD_FILE_START: %s\n", filename.c_str());
// if(!filename.startsWith("/")) { filename = "/" + filename; }
// DBG_OUTPUT_PORT.print("handleFileUpload Name: "); DBG_OUTPUT_PORT.println(filename);
// fsUploadFile = SPIFFS.open(filename, "w");
// filename = String();
return idie("UPLOAD_FILE_START");
} else if (upload.status == UPLOAD_FILE_WRITE) { Serial.println("3");
//DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize);
// if (fsUploadFile) { fsUploadFile.write(upload.buf, upload.currentSize); }
Serial.printf("UPLOAD_FILE_WRITE: %u\n", upload.currentSize);
return idie("UPLOAD_FILE_WRITE");
} else if (upload.status == UPLOAD_FILE_END) { Serial.println("4");
// if (fsUploadFile) { fsUploadFile.close(); }
// DBG_OUTPUT_PORT.print("handleFileUpload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
Serial.printf("UPLOAD_FILE_END: %u\n", upload.totalSize);
if(!WEB.args()) Serial.println("NO ARGS");
else {
for(uint8_t i=0;i<WEB.args();i++) Serial.println("------> ["+WEB.argName(i)+"]=("+WEB.arg(i)+")");
}
return idie("UPLOAD_FILE_END");
}
else { Serial.println("5");
Serial.printf("UPLOAD_ZX\n");
return idie("UPLOAD_XZ");
}
*/
});
WEB.on("/FM",HTTP_GET,[](){ String a=RE("a"); Serial.print("\nFM a="+a);
if(a=="WIFIconn1") {
savefile("wifi_last.txt",RE("net")+"\n"+RE("pass"));
otprav("Reboot...");
ESP.restart();
}
if(a=="WIFIconn") {
String net=RE("net");
String pass=RE("pass");
String s="clean('wifipass'); idie('Reconnect to "+net+"');";
otprav(s);
savefile("wifi_last.txt",net+"\n"+pass);
if(WIFItryConnect(net,pass)) {
Serial.println("========> CONNECT to `"+net+"`");
Serial.println("========> file `wifi_last.txt` saved: "); Serial.println( getfile("wifi_last.txt") );
return;
}
Serial.println("========> ERROR connect to `"+net+"`");
WIFItryMyConnect();
return idip("Error: Net: ["+net+"] / ["+pass+"]");
}
if(a=="WiFi") {
String s="";
int n=WiFi.scanNetworks();
if(n == 0) return otprav("salert('No Networks found',3000);");
for(int i=0; i<n; ++i) {
s+="\n"+String(i+1)+": "+( WiFi.encryptionType(i) == ENC_TYPE_NONE ? " " : "<i class=e_zamok></i>" )+" <div class=ll onclick='WIFIconn"+( WiFi.encryptionType(i) == ENC_TYPE_NONE ? "" : "p" )+"(this.innerHTML)'>"+WiFi.SSID(i)+"</div> ("+WiFi.RSSI(i)+")";
}
return otprav("idie(toTable('"+String(n)+" networks found',\""+njs(s)+"\"))");
}
if(a=="Files") { // список файлов
Dir dir = SPIFFS.openDir("");
String s=""; while(dir.next()) {
String n=h(String(dir.fileName()));
File f=dir.openFile("r");
s+=",'"+n+"':"+String(f.size(),DEC);
}
if(s=="") return otprav("salert('no files',2000)");
return otprav("TabFiles({"+s.substring(1)+"})");
}
if(a=="Info") { return otprav("idie(toTable('System Info',\""+njs(FullInfo())+"\"))"); }
if(a=="Restart") { otprav("salert('Reboot... <img src=ajaxm.gif>',10000); setTimeout('document.location.reload(true)',3000);"); return ESP.restart(); }
if(a=="Upgrade") { return otprav("salert('Upgrade: "+String(UpgradeALL()?"OK":"ERROR")+"',2000)"); }
String file=RE("file"); file.replace("..","");
if(a=="update"||a=="upgrade") {
file.replace(".",""); if(file=="") file="firmware";
upgrade_url(CF("server_update")+file+".bin");
return;
}
if(a=="edit") {
String F=file; F.toUpperCase(); if( F.endsWith(".JPG")||F.endsWith(".JPEG")||F.endsWith(".PNG")||F.endsWith(".GIF")||F.endsWith(".ICO")||F.endsWith(".SVG")) return idie("image","<img src='"+file+"'>");
return otprav("EditFile(\""+njs(file)+"\",\""+njs(getfile(file))+"\")");
}
if(a=="save"){ return idie("Save: "+RE("file")); }
if(a=="del") {
delfile(file);
return otprav("clean(\"file_"+h(file)+"\"); salert(\"Delete: "+h(file)+"\",1000);");
}
if(a=="upload") {
String homeServer=CF("server_update");
file.replace("/","");
String o="";
if(file=="all.list") { Serial.println("========> UPLOAD LIST: ["+homeServer+file+"]");
String s=file_get_contents(homeServer+file);
int i; while(i>=0) { i=s.indexOf("\n"); if(i<0) break;
String fu=s.substring(0,i);
o+="<br>"+fu+" ";
if(fu!="" && ! fu.endsWith(".bin") && fu!="all.list") o+=file_upload_binary_o(homeServer+(homeServer.indexOf("?")>=0 ? "&file=" : "")+fu,fu);
s=s.substring(i+1);
}
} else {
Serial.println("========> UPLOAD BINARY: ["+homeServer+file+"]");
o+="<br>"+file+" "+file_upload_binary_o(homeServer+(homeServer.indexOf("?")>=0 ? "&file=" : "")+file,file);
if(file=="loop.txt") load_loop(file);
}
return otprav("salert(\"Updated:<br>"+o+"\",2000);");
}
return idie("FM error");
});
WEB.on("/AJAX",HTTP_GET,[](){ String a=RE("a"); Serial.print("\na="+a);
if(a=="run") {
String s=RE("s");
Serial.println(" RUN:"+s);
MOTO(s);
return otprav("");
}
if(a=="read") {
uint8_t d=RE0("d");
uint8_t x=digitalRead(d);
Serial.println("Read #`"+String(d)+"`: "+x);
return otprav(String(x));
}
if(a=="aread") {
uint8_t d=A0; // RE0("d");
uint16_t x=analogRead(d);
Serial.println("Analog Read #`A0`: "+x);
return otprav(String(x));
}
if(a=="servo") {
String id=RE("id");
uint8_t x=RE0("x");
Serial.println("Servo #`"+id+"` to #`"+String(x)+"`");
ServoWrite(id,x);
return otprav("");
}
if(a=="MOTO") {
String file=RE("file");
Serial.println("MOTO: "+file);
MOTO(getfile(file));
return otprav("");
}
//http://192.168.2.60/AJAX?a=MOTO&file=SVET.txt
/*
if(a=="text") {
String momma = CF("startfile");
return idie("ok: "+momma);
}
*/
idip("Error a="+a);
});
WEB.onNotFound([](){ WEBFILE(String(WEB.uri())); });
WEB.begin();
}
int Loopi=0,Loopi2=0;
void loop() {
DNS.processNextRequest();
WEB.handleClient();
// if(PINGURL!="" && tim_PingCounter==0) { tim_PingCounter=10; }
if(LOOPFILE!="" && tim_LoopDelay==0) {
int loopstep=1;
Loopi2=LOOPFILE.indexOf("\n",Loopi);
if(Loopi2<0) { Loopi2=0; Loopi=0; }
else {
String M=LOOPFILE.substring(Loopi,Loopi2);
if(M!="") {
Serial.println("LOOP: ["+M+"]");
if(ARG(M,0)=="sleep") tim_LoopDelay=ARG(M,1).toInt();
else {
loopstep=DOMOTO(M); // если wait или что-то еще ожидает
Serial.println("LOOPSTEP == "+String(loopstep));
}
}
if(loopstep) Loopi=++Loopi2;
}
}
}
// ====================================================================
String RE(String n) {
if(!WEB.args()) return "";
for(uint8_t i=0;i<WEB.args();i++) if(WEB.argName(i)==n) return WEB.arg(i);
return "";
}
int RE0(String n) { return RE(n).toInt(); }
void WEBFILE(String path) {
String o = (WEB.method() == HTTP_GET )?"GET":"POST";
o+=": "+path;
if(WEB.args()) { o += "\nArguments:\n"; for(uint8_t i=0;i<WEB.args();i++) o+=" "+String(WEB.argName(i))+": "+String(WEB.arg(i))+"\n"; }
Serial.print(o+"\n");
if(handleFileRead(path)) return;
if(WIFICONNECT!="") return WEBNAH();
String l="http://"+WiFi.softAPIP().toString()+"/";
Serial.println("Redirect: "+l);
WEB.sendHeader("Location",l);
WEB.send(302,"text/plain","Moved Permanently");
}
void WEBNAH() {
WEB.sendHeader("Cache-Control","no-cache, no-store, must-revalidate");
WEB.sendHeader("Pragma","no-cache");
WEB.sendHeader("Expires","-1");
WEB.send(404,"text/plain","404 Not Found");
}
bool handleFileRead(String path){
// Serial.println("Load Web: `"+path+"`");
if(path.endsWith("/")) path += "index.htm";
if(inStopWEBList(path)) return 0;
String pathWithGz = path + ".gz";
if(!SPIFFS.exists(pathWithGz) && !SPIFFS.exists(path)) {
Serial.println("Load Web NOT FOUND: `"+path+"`");
if(path=="/index.htm") { Serial.println("INDEX.HTM: "+DefaultINDEX); WEB.send(200,"text/html",DefaultINDEX); return true; }
return false;
}
if(SPIFFS.exists(pathWithGz)) path = pathWithGz;
File file = SPIFFS.open(path, "r"); if(!file) return false;
// ersetze server mit dem Variablennamen eures ESP8266 Webservers
size_t sent = WEB.streamFile(file,getContentType(path));
file.close();
return true;
}
String MD5file(String file) {
file.replace("/",""); file="/"+file;
if(!SPIFFS.exists(file)) return "";
File f = SPIFFS.open(file,"r"); if(!f) return "";
MD5Builder md5;
md5.begin();
md5.addStream(f,f.size()); // md5.add("Test333");
md5.calculate();
f.close();
return md5.toString();
}
String MD5(String s) {
MD5Builder md5;
md5.begin();
md5.add(s.c_str());
md5.calculate();
return md5.toString();
}
unsigned long filesize(String file) {
file.replace("/",""); file="/"+file;
if(!SPIFFS.exists(file)) return 0;
File f=SPIFFS.open(file,"r"); if(!f) return 0;
return (unsigned long)f.size();
}
String getContentType(String filename){
if(WEB.hasArg("download")) return "application/octet-stream";
else if(filename.endsWith(".htm") || filename.endsWith(".html") ) return "text/html";
// else if(filename.endsWith(".svg")) return "image/svg+xml";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
// else if(filename.endsWith(".xml")) return "text/xml";
// else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
// String ipToString(IPAddress ip){ String s=""; for(int i=0; i<4; i++) { s += i ? ".":""; s+= String(ip[i]); } return s; }
void idip(String s) { Serial.println("\nIDIE: "+s); idie(s); }
void idie(String s) { WEB.send(200,"text/plain","helps('idie',\""+njsn(s)+"\")"); }
void idie(String hm,String s) { WEB.send(200,"text/plain","helps('"+hm+"',\""+njsn(s)+"\")"); }
void otprav(String s) { WEB.send(200,"text/plain",s); }
String njsn(String s) { s.replace("\n",""); s.replace("\r",""); s.replace("\"","\\\""); return s; }
String njs(String s) { s.replace("\n","\\n"); s.replace("\r",""); s.replace("\"","\\\""); return s; }
String h(String s) { s.replace("<","<"); s.replace(">",">"); return s; }
String FullInfo() { return REPER(
"\nChip: {CHIP}"
"\nSoft: {soft}"
"\nServer Update: {server_update}"
"\nAutoupdate: {autoupdate}"
"\nChipID/FlashID: {chip}/{FlashChipId} {CpuFreq} MHz"
"\nPower: {vcc} mV"
"\nWiFi: "+(WIFICONNECT==""?"not connected, setup mode":WIFICONNECT)+""
"\n MAC: {macAddress}"
"\n IP: {ip}:{WEB_PORT}"
"\nServer: "
"\n AP_name: {AP_name}"
"\n AP_password: {AP_password}"
"\n AP_MAC: {softAPmacAddress}"
"\n soft_AP_IP: {softAPIP}"
// "\n AP_mask: {AP_mask}"
// "\n AP_ip: {AP_ip}"
"\nSketchSize: {SketchSize} MD5: {getSketchMD5}"
"\n FreeSketchSpace: {FreeSketchSpace}"
"\n FreeHeap: {FreeHeap}"
"\nFlash Size: {FlashChipSize} / {FlashChipRealSize} / {FlashChipSizeByChipId} bytes"
"\n Flash mode: {flashmode}"
"\n FlashChipSpeed: {FlashChipSpeed}"
"\nCoreVersion: {CoreVersion}"
"\nFullVersion: {FullVersion}"
"\nBootVersion: {BootVersion}"
"\nBootMode: {BootMode}"
"\nResetReason: {ResetReason}"
"\nResetInfo: {ResetInfo}"
"\nCycles: {cycles}"
"\nserver_ping: {server_ping}"
"\nstartfile: {startfile}"
"\nloopfile: {loopfile}"
"\nFiles {Files_count}: {Files}"
"\n"
);
}
String REPER(String s) { String l;
l="{ip}"; if(s.indexOf(l)>=0) s.replace(l, WiFi.localIP().toString() );
l="{macAddress}"; if(s.indexOf(l)>=0) s.replace(l, String(WiFi.macAddress()) );
l="{softAPIP}"; if(s.indexOf(l)>=0) s.replace(l, WiFi.softAPIP().toString() );
l="{softAPmacAddress}"; if(s.indexOf(l)>=0) s.replace(l, String(WiFi.softAPmacAddress()) );
l="{FreeHeap}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getFreeHeap(),DEC) );
l="{FreeSketchSpace}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getFreeSketchSpace(),DEC) );
l="{SketchSize}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getSketchSize(),DEC) );
l="{chip}"; if(s.indexOf(l)>=0) s.replace(l, get_chip() );
l="{CHIP}"; if(s.indexOf(l)>=0) s.replace(l, get_CHIP() );
l="{FlashChipId}"; if(s.indexOf(l)>=0) { String c=String(ESP.getFlashChipId(),HEX); c.toUpperCase(); s.replace(l,c); }
l="{FlashChipSize}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getFlashChipSize(),DEC) );
l="{FlashChipRealSize}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getFlashChipRealSize(),DEC) );
l="{FlashChipSpeed}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getFlashChipSpeed(),DEC) );
l="{cycles}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getCycleCount(),DEC) );
l="{CoreVersion}"; if(s.indexOf(l)>=0) s.replace(l, ESP.getCoreVersion() );
l="{FullVersion}"; if(s.indexOf(l)>=0) s.replace(l, ESP.getFullVersion() );
l="{BootVersion}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getBootMode(),DEC) );
l="{BootMode}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getCycleCount(),DEC) );
l="{CpuFreq}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getCpuFreqMHz(),DEC) );
l="{FlashChipSizeByChipId}"; if(s.indexOf(l)>=0) s.replace(l, String(ESP.getFlashChipSizeByChipId(),DEC) );
l="{getSketchMD5}"; if(s.indexOf(l)>=0) s.replace(l, ESP.getSketchMD5() );
l="{ResetReason}"; if(s.indexOf(l)>=0) s.replace(l, ESP.getResetReason() );
l="{ResetInfo}"; if(s.indexOf(l)>=0) s.replace(l, ESP.getResetInfo() );
l="{flashmode}"; if(s.indexOf(l)>=0) { FlashMode_t m=ESP.getFlashChipMode(); s.replace(l, String(m==FM_QIO?"QIO" : m==FM_QOUT?"QOUT" : m==FM_DIO?"DIO" : m==FM_DOUT ? "DOUT" : "UNKNOWN") ); }
l="{vcc}"; if(s.indexOf(l)>=0) { s.replace(l, String(ESP.getVcc(),DEC) ); }
l="{Files}"; if(s.indexOf(l)>=0) { Dir dir=SPIFFS.openDir(""); String o=""; while(dir.next()) o+=" "+String(dir.fileName()); o.trim(); s.replace(l,o); }
l="{Files_count}"; if(s.indexOf(l)>=0) { int k=0; Dir dir=SPIFFS.openDir(""); while(dir.next()) k++; s.replace(l,String(k)); }
int a=0,b;
while( 1 ) {
a=s.indexOf("{FILE:"); if(a<0) break;
b=s.indexOf("}",a+6); if(b<0) break;
l=s.substring(a+6,b); l.trim();
s.replace(s.substring(a,b+1),getfile(l));
}
a=0;
while( 1 ) {
a=s.indexOf("{",a); if(a<0) break;
b=s.indexOf("}",a+1); if(b<0) break;
l=s.substring(a+1,b);
String lz=CF(l);
s.replace("{"+l+"}",lz);
a+=lz.length();
}
return s;
}
bool delfile(String file) {
file.replace("/",""); file="/"+file;
uint8_t i=SPIFFS.remove(file);
Serial.println("Delete file: "+file+" "+(i?"OK":"ERROR"));
return i;
}
String getfile(String file) {
file.replace("/",""); file="/"+file;
File f=SPIFFS.open(file,"r"); if(!f) return "";
String s=f.readString();
f.close();
return s;
}
void savefile(String file, String s) {
file.replace("/",""); file="/"+file;
// https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266HTTPClient/examples/StreamHttpClient/StreamHttpClient.ino
File f=SPIFFS.open(file,"w"); if(!f) return;
char* data[120];
if(file.endsWith(".jpg") || file.endsWith(".png")) {
// void serial_send(int serial_fd, char *data, int size)
// f.write(0,40); // f,data,
// f.write(0); // f,data,
// f.write(0); // f,data,
// f.write(0); // f,data,
// f.write(0); // f,data,
Serial.println("Can't write BINARY file: "+file); return;
} else f.print(s);
f.close();
}
bool WIFItryConnect(String ssid,String pass) {
//Serial.printf("Default hostname: %s\n", WiFi.hostname().c_str());
//WiFi.hostname("LLEO-TEST_02");
//Serial.printf("New hostname: %s\n", WiFi.hostname().c_str());
// WiFi.mode(WIFI_STA);
// Serial.print("\nWiFi.status: "); Serial.println(WiFi.status());
// Serial.printf("\n Wi-Fi mode set to WIFI_STA %s\n", WiFi.mode(WIFI_STA) ? "" : "Failed!");
// Serial.printf("\n WiFi.getMode(): %d\n", WiFi.getMode());
// WiFi.mode(m): set mode to WIFI_AP, WIFI_STA, WIFI_AP_STA or WIFI_OFF
// WiFi.getMode(): return current Wi-Fi mode (one out of four modes above)
// Serial.printf("\n Connection status: %d\n", WiFi.status());
Serial.print("Try connecting to: "+ssid+" ");
/*
if(WiFi.status() == WL_CONNECTED) {
Serial.print("Disconnecting WiFi"); WiFi.disconnect(false); WIFICONNECT=""; WiFi.disconnect(true);
delay(2000);
}
*/
WiFi.begin(ssid.c_str(),pass.c_str());
for(uint8_t i=0;i<10;i++) {
Serial.print(".");
delay(500);
if(WiFi.status() == WL_CONNECTED) {
Serial.println("Connected \"" +ssid+ "\" IP: " + WiFi.localIP().toString() );
WIFICONNECT=ssid;
return 1;
}
if(WiFi.status() == WL_IDLE_STATUS) Serial.println("\n - - - when Wi-Fi is in process of changing between statuses");
if(WiFi.status() == WL_NO_SSID_AVAIL) Serial.println("\n - - - in case configured SSID cannot be reached");
if(WiFi.status() == WL_CONNECT_FAILED) Serial.println("\n - - - if password is incorrect");
// if(WiFi.status() == WL_DISCONNECTED) Serial.println("\n - - - if module is not configured in station mode");
}
Serial.println(" ERROR connect to \"" +ssid+ "\"" );
return 0;
}
bool WIFItryMyConnect() {
String s=getfile("wifi_last.txt");
if(s!="") {
int i=s.indexOf("\n");
String ssid = s.substring(0,i++);
String pass = s.substring(i);
Serial.println("Try to connect last WiFi: "+ssid);
if( WIFItryConnect(ssid,pass) ) return 1;
}
return 0;
}
bool WIFIinit() {
if(WIFItryMyConnect()) return 1;
if(WIFItryConnect("LLeoNet","trololo123")) return 1; // резервная сетка
// перепробовать все известные нам сети
/*
String s=getfile("wifi_list.txt"); Serial.println("\nLoad: "+s);
if(s!="") {
int i=0,i0=0;
String wifi_net="";
String wifi_pass="";
while(i>=0) {
i=s.indexOf("\n\n",i); if(i<0) break;
i0=s.indexOf("\n",i+=2); if(i0<0) break;
wifi_net=s.substring(i,i0);
wifi_pass=s.substring(i0+=1,s.indexOf("\n",i0));
Serial.println("NETWORK: ["+wifi_net+"] PASSWORD: ["+wifi_pass+"]");
wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1");
}
Serial.println("Connecting Wifi list...");
if(wifiMulti.run() == WL_CONNECTED) {
Serial.println("\nWiFi network \""+WiFi.SSID()+"\" connected IP: "+WiFi.localIP().toString() );
return 1;
}
}
*/
// а иначе - создать точку доступа свою
String AP_name=CF("AP_name");
String AP_password=CF("AP_password");
// String AP_mask=CF("AP_mask");
// String AP_ip=CF("AP_ip");
Serial.println("Create WiFi-network '"+AP_name+"' password: '"+AP_password+"'"); // : IP:"+AP_ip+" MASK:"+AP_mask);
WiFi.mode(WIFI_AP);
// IPAddress ipsmask( ARG(AP_mask,0,".").toInt() , ARG(AP_mask,1,".").toInt() , ARG(AP_mask,2,".").toInt() , ARG(AP_mask,3,".").toInt() );
// IPAddress ips( ARG(AP_ip,0,".").toInt() , ARG(AP_ip,1,".").toInt() , ARG(AP_ip,2,".").toInt() , ARG(AP_ip,3,".").toInt() );
// WiFi.softAPConfig(ips,ips,ipsmask);
if(AP_password!="") WiFi.softAP(AP_name.c_str(),AP_password.c_str()); else WiFi.softAP(AP_name.c_str());
delay(500); // Without delay I've seen the IP address blank
Serial.println("Connected: "+WiFi.softAPIP().toString() );
DNS.setErrorReplyCode(DNSReplyCode::NoError);
DNS.start(53,"*",WiFi.softAPIP());
Serial.println("\n\n"+FullInfo());
return 0;
}
String get_CHIP() { String l=CF("NAME"); return (l!="" ? l : get_chip() ); }
String get_chip() { String l=String(ESP.getChipId(),HEX); l.toUpperCase(); return l; }
String file_upload_binary_o(String url,String file) {
int i=file_upload_binary(url,file);
if(i!=0) return "<font color=red>ERROR #"+String(i)+"</font>";
return "<font color=green>OK</font>";
}
int8_t file_upload_binary(String url,String file) { if(inStopList(file)) return 0;
int8_t res=0;
HTTPClient http;
http.setTimeout(5000);
http.begin(url.c_str());
// Serial.println("File_UPLOAD_BINARY_contents: "+url+" ");
int c = http.GET();
if(c == HTTP_CODE_OK) {
file.replace("/",""); file="/"+file;
// https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266HTTPClient/examples/StreamHttpClient/StreamHttpClient.ino
File f=SPIFFS.open(file,"w"); if(!f) res=-3;
else {
int len = http.getSize();
// create buffer for read
uint8_t buff[128] = { 0 };
// get tcp stream
WiFiClient * stream = http.getStreamPtr();
// read all data from server
while (http.connected() && (len > 0 || len == -1)) {
// get available data size
size_t size = stream->available();
if(size) {
// read up to 128 byte
int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
// write it to f
f.write(buff, c);
if(len > 0) len -= c;
}
delay(1);
}
} f.close();
} else { res=-1; Serial.printf("\terror #%d: %s\n", c, http.errorToString(c).c_str()); }
http.end();
return res;
}
String file_get_contents(String url) {
HTTPClient http;
http.setTimeout(5000);
http.begin(url.c_str());
Serial.println("File_get_contents: ["+url+"]");
int c = http.GET();
String s="";
if(c == HTTP_CODE_OK) s=http.getString();
else Serial.printf("\terror #%d: %s\n", c, http.errorToString(c).c_str());
http.end();
return s;
}
bool ServoDetach(String n) {
if(!ServoAttached(n)) return 0;
uint8_t ni=servopins[n.toInt()];
if(n=="1") { servo1.detach();/* pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else if(n=="2") { if(ni!=-1) servo2.detach(); /*pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else if(n=="3") { if(ni!=-1) servo3.detach(); /*pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else if(n=="4") { if(ni!=-1) servo4.detach(); /*pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else if(n=="5") { if(ni!=-1) servo5.detach(); /*pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else if(n=="6") { if(ni!=-1) servo6.detach(); /*pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else if(n=="7") { if(ni!=-1) servo7.detach(); /*pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else if(n=="8") { if(ni!=-1) servo8.detach(); /*pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else if(n=="9") { if(ni!=-1) servo9.detach(); /*pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else if(n=="10") { if(ni!=-1) servo10.detach(); /*pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else if(n=="11") { if(ni!=-1) servo11.detach(); /*pinMode(ni,OUTPUT); digitalWrite(ni,0);*/ }
else Serial.print(" error N");
return ServoAttached(n);
}
bool ServoAttach(String n, uint8_t d) {
uint8_t i=n.toInt(); if(i<1 || i>6) { Serial.println(" error N"); return -1; }
if(ServoAttached(n)) return 1;
if(n=="1") servo1.attach(d);
else if(n=="2") servo2.attach(d);
else if(n=="3") servo3.attach(d);
else if(n=="4") servo4.attach(d);
else if(n=="5") servo5.attach(d);
else if(n=="6") servo6.attach(d);
else if(n=="7") servo7.attach(d);
else if(n=="8") servo8.attach(d);
else if(n=="9") servo9.attach(d);
else if(n=="10") servo10.attach(d);
else if(n=="11") servo11.attach(d);
servopins[i]=d;
tim_motor_detach=3;
return ServoAttached(n);
}
void ServoWrite(String n, int x) {
int i=n.toInt(); if(i<1 || i>6) { Serial.println(" error N"); return; }
tim_motor_detach=2;
ServoAttach(n,servopins[i]);
Serial.println("... ServoWrite("+n+":"+String(servopins[i])+") = "+String(x));
if(n=="1") servo1.write(x);
else if(n=="2") servo2.write(x);
else if(n=="3") servo3.write(x);
else if(n=="4") servo4.write(x);
else if(n=="5") servo5.write(x);
else if(n=="6") servo6.write(x);
else if(n=="7") servo7.write(x);
else if(n=="8") servo8.write(x);
else if(n=="9") servo9.write(x);
else if(n=="10") servo10.write(x);
else if(n=="11") servo11.write(x);
}
bool ServoAttached(String n) {
int i=-1;
if(n=="1") i=servo1.attached();
else if(n=="2") i=servo2.attached();
else if(n=="3") i=servo3.attached();
else if(n=="4") i=servo4.attached();
else if(n=="5") i=servo5.attached();
else if(n=="6") i=servo6.attached();
else if(n=="7") i=servo7.attached();
else if(n=="8") i=servo7.attached();
else if(n=="9") i=servo8.attached();
else if(n=="10") i=servo10.attached();
else if(n=="11") i=servo11.attached();
else { Serial.print(" error N"); return 0; }
// Serial.println("\n ... ServoAttach("+n+") = "+i);
return i;
}
void MOTO(String s) { if(s=="") return; s.replace(";","\n");
int i; while(i>=0) {
i=s.indexOf("\n"); if(i<0) { if(s.length()) DOMOTO(s); break; }
DOMOTO(s.substring(0,i));
s=s.substring(i+1);
}
}
bool DOMOTO(String s) { s=nocomments(s); s.trim(); if(s=="") return 1; String cmd=ARG(s,0);
if(cmd=="stop") { LOOPFILE=""; Serial.println("STOP LOOP"); return 1; }
if(cmd=="loop") { String a=ARG(s,1); if(a=="") a="loop.txt"; Serial.println("START LOOP: "+a); load_loop(a); return 1; }
if(cmd=="ping") { String url=REPER(ARG(s,1)); String otv=file_get_contents(url); Serial.println("PING: " + url + " = ["+otv+"]"); MOTO(otv); return 1; }
if(cmd=="attach") { ServoAttach( ARG(s,1), ARG(s,2).toInt() ); return 1; }
if(cmd=="detach") { ServoDetach( ARG(s,1) ); return 1; }
if(cmd=="go") { ServoWrite( ARG(s,1), ARG(s,2).toInt() ); return 1; }
if(cmd=="pinmode") {
uint8_t d=ARG(s,1).toInt();
String mode=ARG(s,2);
if(mode=="INPUT_PULLUP") pinMode(d,INPUT_PULLUP);
else if(mode=="INPUT") pinMode(d,INPUT);
else pinMode(d,OUTPUT);
return 1;
}
if(cmd=="pin") { digitalWrite(ARG(s,1).toInt(),ARG(s,2).toInt()); return 1; }
if(cmd=="delay") { delay(ARG(s,1).toInt()); return 1; }
if(cmd=="run") { MOTO(getfile(ARG(s,1))); return 1; }
if(cmd=="wait") { // wait 2 < 10
uint8_t port=ARG(s,1).toInt();
String z=ARG(s,2);
uint16_t v=ARG(s,3).toInt();
uint16_t x;
bool e;
if(z == "=") { x=digitalRead(port); e=(x == v ? 0 : 1 ); }
else if(z == "!=") { x=digitalRead(port); e=(x != v ? 0 : 1 ); }
else {
x=analogRead(A0);
if(z == ">") e=(x > v ? 0 : 1 );
else if(z == ">=") e=(x >= v ? 0 : 1 );
else if(z == "<") e=(x < v ? 0 : 1 );
else if(z == "<=") e=(x <= v ? 0 : 1 );
else { Serial.println("Error WAIT: "+s); return 1; }
}
// Serial.println(" . . . . WAIT: port `"+String(1*port)+"` ["+String(x)+"] "+z+" ("+String(v)+") --> "+String(e) );
return e;
}
MOTO(getfile(cmd));
return 1;
}
String ARG(String s,int n,String sep) { int i=0;for(int j=0;j<n;j++) { i=s.indexOf(sep,i)+1; if(i<=0) return ""; } return s.substring(i,s.indexOf(sep,i+1)); }
String ARG(String s,int n) { return ARG(s,n," "); }
/*
String d=RE("d");
if(ServoAttached(n)) { ServoDetach(n); s+=" [detach] "; }
s+" #"+d;
if(ServoAttach(n,d.toInt())) return idip(s+" OK");
*/
String nocomments(String s) { int j=s.indexOf("#"); if(j>=0) { s=s.substring(0,j); s.trim(); } return s; }
String CF(String v,String D) {
if(LOADED_CONFIG=="NO") {
LOADED_CONFIG=getfile("config.txt");
if(LOADED_CONFIG=="") LOADED_CONFIG=DefaultConfig;
LOADED_CONFIG.replace("\t"," "); LOADED_CONFIG.replace("\r","");
LOADED_CONFIG=LOADED_CONFIG+"\n";
}
int i=0,i2; while(i>=0) { i2=LOADED_CONFIG.indexOf("\n",i); if(i2<0) break;
String c=LOADED_CONFIG.substring(i,i2); i=++i2;
c=nocomments(c); if(c=="") continue;
int r=c.indexOf("="); if(r<0) continue;
String n = c.substring(0,r); n.trim();
if(n!=v) continue;
c=c.substring(r+1); c.trim();
if(c.indexOf("{")>=0) c=REPER(c);
return c;
}
return D;
}
int CF0(String v,int D) { String c=CF(v,""); c.toUpperCase(); if(c=="NO"||c=="FALSE") c="0"; else if(c=="YES"||c=="TRUE") c="1"; return (c==""?D:c.toInt()); }
String CF(String v) { return CF(v,""); }
int CF0(String v) { return CF0(v,0); }
void load_loop(String s) { Loopi=0; Loopi2=0; tim_LoopDelay=0; LOOPFILE=CF("loop"); if(LOOPFILE!="") LOOPFILE.replace(";","\n"); else {
// String s=CF("loopfile"); if(s!="")
LOOPFILE=getfile(s); } if(LOOPFILE!="") LOOPFILE+="\n"; }
String StopWebList="NO";
String StopList="NO";
bool inStopWEBList(String file) { if(StopWebList=="NO") StopWebList=getfile("stopweblist.txt"); if(StopWebList=="") return 0; return inStop(StopWebList,file); }
bool inStopList(String file) { if(StopList=="NO") StopList=getfile("stoplist.txt"); if(StopList=="") return 0; return inStop(StopList,file); }
bool inStop(String s,String file) { file.replace("/",""); file="/"+file;
int i=0; while(1) {
String l=ARG(s,i++,"\n"); if(l=="") return 0;
if(file.startsWith(l)) { Serial.println("Deprecated file: `"+file+"`"); return 1; }
}
return 0;
}
bool upgrade_url(String file) {
if(inStopList(file)) return 0;
t_httpUpdate_return ret;
Serial.println("Update new sketch "+file);
pinMode(2,OUTPUT);digitalWrite(2,0); // ВКЛЮЧИТЬ ЛАМПУ
ESPhttpUpdate.rebootOnUpdate(true);
ret = ESPhttpUpdate.update(file);
digitalWrite(2,1); // ПОГАСИТЬ ЛАМПУ
switch(ret) {
case HTTP_UPDATE_FAILED: {
String err=ESPhttpUpdate.getLastErrorString();
if(err.indexOf("reset")>=0) { idip("Press RESET and repeat!"); ESP.reset(); break; }
idip("UPDATE ERROR ["+file+"]: "+err);
break;
}
case HTTP_UPDATE_NO_UPDATES: idip("HTTP_UPDATE_NO_UPDATES"); break;
case HTTP_UPDATE_OK: idip("HTTP_UPDATE_OK"); break;
default: idip("OTHER"); break;
}
}
bool UpgradeALL() {
String s=CF("server_update"); if(s=="") return 0;
String otv=file_get_contents(REPER(s)); // Serial.print(" ["+otv+"]");
if(ARG(otv,0,"\n")!="OK") return 0;
String firmware_md5="";
int i=1; while(1) {
String s=ARG(otv,i++,"\n"); if(s=="") break;
String file=ARG(s,0," ");
String md5=ARG(s,1," ");
if(file=="firmware.bin") { firmware_md5=md5; continue; }
if(MD5file(file)==md5) continue;
Serial.print("UPDATE "+file+": ");
int i=file_upload_binary(CF("server_update")+"&file="+file,file); if(i==0 && MD5file(file)==md5) Serial.println("OK"); else Serial.println("ERROR #"+String(i));
}
if(firmware_md5 != "" && firmware_md5 != ESP.getSketchMD5() ) { Serial.println("firmware.bin need to UPDATE"); upgrade_url(CF("server_update")+"&file=firmware.bin"); }
return 1;
}